﻿using System.Windows.Media.Animation;
using System.Windows;

namespace ThunderboltCustomControlLibrary;

public static class AnimationHelper
{
	#region Slide In / Out
	/// <summary> 淡入淡出 </summary>

	public static async Task SlideAndFadeInAsync(this FrameworkElement element, AnimationSlideInDirection direction, float seconds = 0.3f, bool keepMargin = true, int size = 0)
	{
		var sb = new Storyboard();
		//取消滑入滑出，只有淡入淡出
		//switch (direction)
		//{
		//	case AnimationSlideInDirection.Left:
		//		sb.AddSlideFromLeft(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Right:
		//		sb.AddSlideFromRight(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Top:
		//		sb.AddSlideFromTop(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Bottom:
		//		sb.AddSlideFromBottom(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//}

		sb.AddFadeIn(seconds);
		sb.Begin(element);
		element.Visibility = Visibility.Visible;
		await Task.Delay((int)(seconds * 1000));
	}

	public static async Task SlideAndFadeOutAsync(this FrameworkElement element, AnimationSlideInDirection direction, float seconds = 0.3f, bool keepMargin = true, int size = 0)
	{
		var sb = new Storyboard();

		//switch (direction)
		//{
		//	case AnimationSlideInDirection.Left:
		//		sb.AddSlideToLeft(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Right:
		//		sb.AddSlideToRight(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Top:
		//		sb.AddSlideToTop(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//	case AnimationSlideInDirection.Bottom:
		//		sb.AddSlideToBottom(seconds, size == 0 ? element.ActualWidth : size, keepMargin: keepMargin);
		//		break;
		//}

		sb.AddFadeOut(seconds);
		sb.Begin(element);
		element.Visibility = Visibility.Visible;
		await Task.Delay((int)(seconds * 1000));
	}

	#endregion

	#region Fade In / Out

	public static async Task FadeInAsync(this FrameworkElement element, bool firstLoad, float seconds = 0.3f)
	{
		var sb = new Storyboard();
		sb.AddFadeIn(seconds);
		sb.Begin(element);
		element.Visibility = Visibility.Visible;
		await Task.Delay((int)(seconds * 1000));
	}

	public static async Task FadeOutAsync(this FrameworkElement element, float seconds = 0.3f)
	{
		var sb = new Storyboard();
		sb.AddFadeOut(seconds);
		sb.Begin(element);
		element.Visibility = Visibility.Visible;
		await Task.Delay((int)(seconds * 1000));
		element.Visibility = Visibility.Collapsed;
	}

	#endregion


	#region 左边滑入滑出动画  Sliding To/From Left

	/// <summary>
	/// 添加一个从左边滑入的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideFromLeft(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个左侧边缘滑入的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(-offset, 0, keepMargin ? offset : 0, 0),
			To = new Thickness(0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	/// <summary>
	/// 添加一个从左边滑出的动画到故事板（Storyboard）上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideToLeft(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个左侧边缘滑出的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0),
			To = new Thickness(-offset, 0, keepMargin ? offset : 0, 0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	#endregion

	#region 右边滑入滑出动画  Sliding To/From Right

	/// <summary>
	/// 添加一个从右边滑入的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideFromRight(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个右侧边缘滑入的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(keepMargin ? offset : 0, 0, -offset, 0),
			To = new Thickness(0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	/// <summary>
	/// 添加一个从右边滑出的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideToRight(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个右侧边缘滑出的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0),
			To = new Thickness(keepMargin ? offset : 0, 0, -offset, 0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	#endregion

	#region 顶部滑入滑出动画  Sliding To/From Top

	/// <summary>
	/// 添加一个从顶部滑入的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideFromTop(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个顶部边缘滑入的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0, -offset, 0, keepMargin ? offset : 0),
			To = new Thickness(0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	/// <summary>
	/// 添加一个从顶部滑出的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideToTop(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个顶部边缘滑出的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0),
			To = new Thickness(0, -offset, 0, keepMargin ? offset : 0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	#endregion

	#region 底部滑入滑出动画  Sliding To/From Bottom

	/// <summary>
	/// 添加一个从底部滑入的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideFromBottom(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个顶部边缘滑入的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0, keepMargin ? offset : 0, 0, -offset),
			To = new Thickness(0),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	/// <summary>
	/// 添加一个从底部滑出的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	/// <param name="offset">从左边开始的距离</param>
	/// <param name="decelerationRatio">减速率</param>
	/// <param name="keepMargin">动画期间是否保持元素的宽度相同</param>
	public static void AddSlideToBottom(this Storyboard storyboard, float seconds, double offset, float decelerationRatio = 0.9f, bool keepMargin = true)
	{
		// 创建一个底部边缘滑出的动画 
		var animation = new ThicknessAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = new Thickness(0),
			To = new Thickness(0, keepMargin ? offset : 0, 0, -offset),
			DecelerationRatio = decelerationRatio
		};

		// 设置动画目标属性的名称 Margin
		Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}

	#endregion

	#region 淡入淡出效果   Fade In/Out

	/// <summary>
	/// 添加一个淡入的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	public static void AddFadeIn(this Storyboard storyboard, float seconds)
	{
		// 创建一个渐变出现的动画
		var animation = new DoubleAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = 0,
			To = 1,
		};

		// 设置动画目标属性的名称 Opacity
		Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}


	/// <summary>
	/// 添加一个淡出的动画到故事板 <see cref="Storyboard"/> 上
	/// </summary>
	/// <param name="storyboard">承载动画的故事板</param>
	/// <param name="seconds">动画时长</param>
	public static void AddFadeOut(this Storyboard storyboard, float seconds)
	{
		// 创建一个渐变消失的动画
		var animation = new DoubleAnimation
		{
			Duration = new Duration(TimeSpan.FromSeconds(seconds)),
			From = 1,
			To = 0,
		};

		// 设置动画目标属性的名称 Opacity
		Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));

		// 将动画添加到当前故事板上
		storyboard.Children.Add(animation);
	}
 
        #endregion


}
/// <summary>
/// 动画滑动方法
/// </summary>
public enum AnimationSlideInDirection
{
	/// <summary>
	/// 无方向动画
	/// </summary>
	None = 0,
	/// <summary>
	/// 左测滑入
	/// </summary>
	Left = 1,
	/// <summary>
	/// 右测滑入
	/// </summary>
	Right = 2,
	/// <summary>
	/// 顶部滑入
	/// </summary>
	Top = 3,
	/// <summary>
	/// 底部滑入
	/// </summary>
	Bottom = 4
}